#include "renrendaigetdetail.h"
#include "pthread.h"
#include "renrendai.h"
#include "worker.h"
#define RSP_OK          0
#define RSP_TOOFAST     1
#define RSP_UNKNOW      2

#define TOOFASTCODE     302
/* BUG 修复:
   1. 车产，房产出现直接说明什么车的，不能简单的使用checkbox
 */
int total = 0;

int DebitDetail_Init(struct WorkerEnv *wenv);
int DebitDetail_MakeReq(struct HttpReq **req);
int DebitDetail_Parse(struct HttpReq* req);
int DebitDetail_AfterParse(struct HttpReq* req);
int DebitDetail_FinishForWorker(struct WorkerEnv *wenv);
int DebitDetail_FinishForReq(struct HttpReq *req);
struct WorkerInitStruct debitdetail
=   {   "renrendai debitdetail",           /* 任务名 */
	10,     // 10s          /* 超时时间 */
	200,
	20,                     /* 任务最大并发数 */
	"debitdetail.log",             /* 日志文件 */
	DebitDetail_Init,            /* 初始化函数 */
	DebitDetail_MakeReq,        /* 生成HttpReq */
	NULL,                   /* 检查响应是否正确 */
	NULL,                   /* 解析header */
	DebitDetail_Parse	,   /* 解析body */
	DebitDetail_AfterParse,             /* 解析完毕后的函数 */
	DebitDetail_FinishForWorker,                    /* 任务退出前函数 */
	DebitDetail_FinishForReq                    /* 退出前对任务队列和正在运行的httpreq进行处理 */
};
struct WorkerEnv *gDebitdetailWenv;

/** 输入loanid **/
#define ARRAYMAXNUM		10000
long *gLoanids = NULL;
int gGetindex = 0;
int gSetindex = 0;
pthread_mutex_t gLoanidarray_Lock = PTHREAD_MUTEX_INITIALIZER;

struct DebitDetailInputStruct {
	long loanid;
	int toofast;
};

static char headerDetail[] =	"Host: www.renrendai.com\r\nConnection: keep-alive\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0\r\n"
"Referer: http://www.renrendai.com/lend/loanList.action";

static char urlDetail[]=	"http://www.renrendai.com/lend/detailPage.action?loanId=%ld";

static char cookieDetail[] =	"rrdLoginCartoon=rrdLoginCartoon; __ag_cm_=1423494200987; JSESSIONID=%s; "
"jforumUserInfo=dlQO30a6F5fYQjwX\%2FWwvEz\%2FlQM4RGv1J\%0A; IS_MOBLIE_IDPASS=true-true; "
"activeTimestamp=1287270; renrendaiUsername=\"\"; Hm_lvt_2547238860b5ae69d69cae60a725236c=1422806083,1423494201,1423578209; "
"Hm_lpvt_2547238860b5ae69d69cae60a725236c=1423578241; Hm_lvt_71ce3105a964d0c3748e04584e5af0b9=1422806083,1423494201,1423578209; "
"Hm_lpvt_71ce3105a964d0c3748e04584e5af0b9=1423578241; ag_fid=uSVlmKfTwCMVGlOF";
static HtmlPathNode uipath[] =
{
	{ GUMBO_TAG_BODY , UNDEFINED, GUMBO_NODE_ELEMENT, {""}, {""} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"class"}, {"pg-container"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"class"}, {"pg-container-content"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"id"}, {"pg-loan-invest"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"id"}, {"loan-details"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"id"}, {"loan-tab-content"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {""}, {""} },  /* class = ui-box-whith-bg fn-clear */
	{ GUMBO_TAG_DIV , 1, GUMBO_NODE_ELEMENT, {"data-name"}, {"info"} },
	{ GUMBO_TAG_DIV , 1, GUMBO_NODE_ELEMENT, {""}, {""} },  /* ui-tab-context-basic */
	{ GUMBO_TAG_UL , 1, GUMBO_NODE_ELEMENT, {""}, {""} },   /* ui-tab-list fn-clear */
	__HTMLPATHNODEEND__
};
/* 性别和昵称 */
static HtmlPathNode nicknameandsexpath[] = 
{
	{ GUMBO_TAG_LI , 1, GUMBO_NODE_ELEMENT, {""}, {""} },
	{ GUMBO_TAG_SPAN , 2, GUMBO_NODE_ELEMENT, {"class"}, {"tab-list-value"} },
	{ GUMBO_TAG_EM , 1, UNDEFINED, {""}, {""} },
	__HTMLPATHNODEEND__
};

static HtmlPathNode userdetailpath[] =
{
	{ GUMBO_TAG_LI , 0, GUMBO_NODE_ELEMENT, {""}, {""} },
	{ GUMBO_TAG_SPAN , 2, GUMBO_NODE_ELEMENT, {"class"}, {"tab-list-value"} },
	{ UNDEFINED , UNDEFINED, GUMBO_NODE_TEXT, {""}, {""} },
	__HTMLPATHNODEEND__
};

/* checkbox信息 */
static HtmlPathNode checkboxpath[] =
{
	{ GUMBO_TAG_LI , 0, GUMBO_NODE_ELEMENT, {""}, {""} },
	{ GUMBO_TAG_SPAN , 2, GUMBO_NODE_ELEMENT, {"class"}, {"tab-list-value"} },
	/* 这里注意直接找第一个span，判断后面的class属性，如果找不到说明为无 */
	{ GUMBO_TAG_SPAN, 1, GUMBO_NODE_ELEMENT, {"class"}, {"mr20"} },		
	{ GUMBO_TAG_I, 1, GUMBO_NODE_ELEMENT, {"class"}, {"icon icon-check-checked mr5"} },
	__HTMLPATHNODEEND__
};

/* 车产房产直接是详细信息 */
static HtmlPathNode propertypath[] =
{
	{ GUMBO_TAG_LI , 0, GUMBO_NODE_ELEMENT, {""}, {""} },
	{ GUMBO_TAG_SPAN , 2, GUMBO_NODE_ELEMENT, {"class"}, {"tab-list-value"} },
	{ GUMBO_TAG_SPAN, 1, GUMBO_NODE_ELEMENT, {"class"}, {"mr20"} },
	{ GUMBO_TAG_EM, 1, GUMBO_NODE_ELEMENT, {""}, {""} },
	__HTMLPATHNODEEND__
};
static HtmlPathNode useridpath[] =
{
	{ GUMBO_TAG_BODY , UNDEFINED, GUMBO_NODE_ELEMENT, {""}, {""} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"class"}, {"pg-container"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"class"}, {"pg-container-content"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"id"}, {"pg-loan-invest"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"id"}, {"loan-details"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {"id"}, {"loan-tab-content"} },
	{ GUMBO_TAG_DIV , UNDEFINED, GUMBO_NODE_ELEMENT, {""}, {""} },  /* class = ui-box-whith-bg fn-clear */
	{ GUMBO_TAG_DIV , 1, GUMBO_NODE_ELEMENT, {"data-name"}, {"info"} },
	{ GUMBO_TAG_DIV , 1, GUMBO_NODE_ELEMENT, {""}, {""} },  /* ui-tab-context-basic */
	{ GUMBO_TAG_H4 ,  1, GUMBO_NODE_ELEMENT, {""}, {""} },   /* ui-tab-content-title color-dark-text */
	{ GUMBO_TAG_SPAN , 1, GUMBO_NODE_ELEMENT, {""}, {""} }, /* mll0 */
	{ UNDEFINED , UNDEFINED, GUMBO_NODE_TEXT, {""}, {""} },
	__HTMLPATHNODEEND__
};

const int DEDIT_SAMPLENUM = 20;
int debit_sampleresult; /* 按照比特计算 */
int currentsamplenum = 0;
int currentsamplefast = 0;
#define BEBIT_SAMPLEMASK	0xFFF;

int DebitDetail_Init(struct WorkerEnv *wenv)
{
	gDebitdetailWenv = wenv;
	gLoanids = (long*)(malloc(sizeof(long) * ARRAYMAXNUM));
	if (gLoanids == NULL) {
		ErrorLog(__FILE__, __LINE__, "申请内存出错");
		return SPIDER_MEM_ERR;
	}

	gSetindex = gGetindex = 0;

	debit_sampleresult = 0;
	return 0;
}

int SetLoanIdForDebitDetail(long loanid)
{
	pthread_mutex_lock(&gLoanidarray_Lock);

	/* FIXME: 这样判断是否初始化不是很对 */
	if (gLoanids) {
		if ((gSetindex + 1) % ARRAYMAXNUM == gGetindex) {
			ErrorLog(__FILE__, __LINE__, "存放loanid的数组已经饱和[%ld]被丢弃", loanid);
			pthread_mutex_unlock(&gLoanidarray_Lock);
			return SPIDER_INTERNAL_ERR;
		}
		gLoanids[gSetindex] = loanid;
	}
	gSetindex++;
	total++;
	if (gSetindex == ARRAYMAXNUM)
		gSetindex = 0;

	pthread_mutex_unlock(&gLoanidarray_Lock);

	return 0;
}

int GetLoanId(long *loanid)
{
	pthread_mutex_lock(&gLoanidarray_Lock);
	//printf("getindex[%d]-setindex[%d]\n", gGetindex, gSetindex);
	if (gSetindex == gGetindex) {
		/* FIXBUG: 这里没有释放会导致死锁 */
		pthread_mutex_unlock(&gLoanidarray_Lock);
		return SPIDER_NOTFOUND_ERR;
	}
	*loanid = gLoanids[gGetindex]; 
	gGetindex++;
	if (gGetindex == ARRAYMAXNUM)
		gGetindex = 0;

	pthread_mutex_unlock(&gLoanidarray_Lock);

	return 0;
}

int PrintRenrendai_detail(RenrendaiUser *user, long loanid)
{
	if (user == NULL) {
		ErrorLog(__FILE__, __LINE__, "输入的user为空");
		return 0;
	}

	FILE *file = fopen("./userdetail.dat", "a+");

	fprintf(file, "USERID[%ld]-NICKNAME[%s]++++++++++++++++++++++++++++++++\n", loanid, user->nickName);
	if (user->male == 1) 
		fprintf(file, "性别:男");
	else 
		fprintf(file, "性别:女");
	fprintf(file ,"\t行业:%s\t收入范围:%s\t年龄:%d\t公司规模:%s",
			user->compIndustry,
			user->income,
			user->age,
			user->compScale );
	fprintf(file, "\n");
	if (user->isMarriage == 1)
		fprintf(file ,"结婚:%s", "已婚");
	else 
		fprintf(file ,"结婚:%s", "未婚");

	if (user->haveHouse == 1)
		fprintf(file ,"\t房产:%s", "有");
	else 
		fprintf(file ,"\t房产:%s", "无");

	if (user->houseDebit == 1)
		fprintf(file ,"\t房贷:有");
	else 
		fprintf(file ,"\t房贷:无");

	if (user->haveCar == 1)
		fprintf(file ,"\t车产:有");
	else 
		fprintf(file ,"\t车产:无");
	if (user->carDebit == 1)
		fprintf(file ,"\t车贷:有");
	else 
		fprintf(file ,"\t车贷:无");

	fprintf(file, "\n");
	fprintf(file ,"学历:%s", user->education);
	fprintf(file ,"职位:%s", user->position);
	fprintf(file ,"\t学校:%s", user->school);
	fprintf(file ,"\t工作城市:%s", user->city);
	fprintf(file ,"\t工作年限:%s", user->workage);

	fprintf(file, "\n");
	fprintf(file, "--------------------------------------------------------\n");
	fclose(file);

	return 0;
}

/** 房产 车产 房贷 车贷
 *	1. 返回1表示有
 *	2. 返回0表示无
 * 3. 返回负数表示出错
 **/

static int _GetCheckBoxInfo(GumboNode *info, int index)
{
	int findCheck = 0, findUnCheck = 0;
	int findDetail = 0;
	GumboNode *checkbox = NULL;

	checkboxpath[0].index = index;
	strcpy(checkboxpath[3].attrvalue[0], CHECK);
	findCheck = WalkHtmlPath(info, checkboxpath, &checkbox);
	strcpy(checkboxpath[3].attrvalue[0], UNCHECK);
	findUnCheck = WalkHtmlPath(info, checkboxpath, &checkbox);
	if (findCheck && findUnCheck) {
		/*  <span class="tab-list-value">
			<span class="mr20"> 2012年购
			<em title="东风悦达起亚">
			东风悦达...
			</em>
			</span>
			</span> */
		/* 如果查找checkbox出错 */
		propertypath[0].index = index;
		findDetail = WalkHtmlPath(info, propertypath, &checkbox); 
		if (findDetail == 0) 
			return 1;
		else {
			ErrorLog(__FILE__, __LINE__, "获得detail查看checkbox出错");
			return RENRENDAI_DETAIL_PARSECHECKBOX;
		}
	}
	else if(findCheck == 0){
		return 1;
	}
	else {
		return 0;
	}
}

static int DebitDetail_GetUserInfo(GumboOutput *output, RenrendaiUser *user)
{
	char orgattrvalue[101];
	GumboNode *root = NULL;
	GumboNode *info = NULL;
	int findCheck = 0;
	int findUnCheck = 0;
	int i = 0;
	int ret = 0;

	if (!output || !user)
		return SPIDER_ARG_ERR;

	root = output->root;
	ret = WalkHtmlPath(root, uipath, &info);
	if (ret) {
		ErrorLog(__FILE__, __LINE__, "获得用户详细信息UL节点出错");
		return ret;
	}

	/* 昵称,性别 */
	for (i = 1; i <= 2; i++) {
		char strTemp[101];
		int len;
		memset(strTemp, 0x00, sizeof(strTemp));

		nicknameandsexpath[2].index = i;
		ret = HtmlGetAttrValueByPath(info, nicknameandsexpath, "title", strTemp, sizeof(strTemp) - 1);
		if (ret) {
			ErrorLog(__FILE__, __LINE__, "ret[%d]-i[%d]", ret, i);
			return i;
		}
		switch(i) {
			case 1:
				len = strlen(strTemp);
				if (strlen(strTemp) > sizeof(user->nickName) - 1)
					len = sizeof(user->nickName) - 1;
				strncpy(user->nickName, strTemp, len);
				break;
			case 2:
				if (strcmp(strTemp, "男") == 0) 
					user->male = 1;
				else
					user->male = 0;
				break;
		}
	}

	/* 行业 年龄 收入范围 */
	for (i = 2; i <= 14; i++) {
		if (i == 6 || i == 9 || i == 10 || i == 12 || i == 15)
			continue;
		char strTemp[101];
		int len;
		memset(strTemp, 0x00, sizeof(strTemp));
		userdetailpath[0].index = i; 
		if (i == 8) {
			memset(orgattrvalue, 0x00, sizeof(orgattrvalue));
			strcpy(orgattrvalue, userdetailpath[1].attrvalue[0]);
			strcpy(userdetailpath[1].attrvalue[0], "tab-list-value fn-text-overflow");
		}
		ret = HtmlGetTextByPath(info, userdetailpath, strTemp, sizeof(strTemp) - 1);
		if (ret) {
			ErrorLog(__FILE__, __LINE__, "ret[%d]-i[%d]", ret, i);
			return i;
		}
		switch(i) {
			case 2:
				strcpy(user->compIndustry, strTemp); break;
			case 3:
				strcpy(user->income, strTemp);		break;
			case 4:
				user->age = atoi(strTemp);			break;
			case 5:
				strcpy(user->compScale, strTemp);	break;
			case 7:
				strcpy(user->education, strTemp);	break;
			case 8:
				strcpy(userdetailpath[1].attrvalue[0], orgattrvalue);
				strcpy(user->position, strTemp);		break;
			case 11:
				strcpy(user->city, strTemp);			break;
			case 13:
				if (strcmp("未婚", strTemp) == 0)
					user->isMarriage = 0;
				else 
					user->isMarriage = 1;
				break;
			case 14:
				strcpy(user->workage, strTemp);		break;
		}
	}

	/* 用户id */
	char struserid[21];
	memset(struserid, 0x00, sizeof(struserid));
	ret = HtmlGetTextByPath(root, useridpath, struserid, sizeof(struserid) - 1);
	if (ret) {
		ErrorLog(__FILE__, __LINE__, "解析USERID出错");
		return ret;
	}

	/* 房产，车产，房贷，车贷 */
	ret = _GetCheckBoxInfo(info, 6);
	if(ret == 1){
		user->haveHouse = 1;
	}
	else if (ret == 0){
		user->haveHouse = 0;
	}
	else {
		/* error */
		ErrorLog(__FILE__, __LINE__, "解析房产出错");
		return ret;
	}

	ret = _GetCheckBoxInfo(info, 9);
	if(ret == 1){
		user->houseDebit = 1;
	} else if (ret == 0){
		user->houseDebit = 0;
	} else {
		/* error */
		ErrorLog(__FILE__, __LINE__, "解析房贷出错");
		return ret;
	}  

	ret = _GetCheckBoxInfo(info, 12);
	if(ret == 1){
		user->haveCar = 1;
	} else if (ret == 0){
		user->haveCar = 0;
	} else {        
		/* error */             
		ErrorLog(__FILE__, __LINE__, "解析车产出错");
		return ret;
	} 

	ret = _GetCheckBoxInfo(info, 15);
	if(ret == 1){
		user->carDebit = 1;
	} else if (ret == 0){
		user->carDebit = 0;
	} else {        
		/* error */             
		ErrorLog(__FILE__, __LINE__, "解析车贷出错");
		return ret;
	} 
	return 0;
}

int DebitDetail_Parse(struct HttpReq* req)
{
	int ret = 0;
	Buf *body = NULL; 	
	GumboOutput *output = NULL;
	RenrendaiUser user;
	struct DebitDetailInputStruct *input = GetHttpReqInputData(req);
	long loanid = input->loanid;

	/* 添加错误次数等到after阶段添加 */
	currentsamplenum++;
	ret = CheckResp(req);
	if (ret == RSP_TOOFAST) {
		currentsamplefast++;
	}

	if (currentsamplenum == DEDIT_SAMPLENUM) {
		if (currentsamplefast >= 5) {
				ErrorLog(__FILE__, __LINE__, "太快了-减慢时间-休息一会");
				ModifyDelaytime(gDebitdetailWenv, 500);
ErrorLog(__FILE__, __LINE__, "TIME[%d]", gDebitdetailWenv->delaytime);

		}
		// 所有的都是对的,说明可以加快速度 
		else if (currentsamplefast == 0) {
			ErrorLog(__FILE__, __LINE__, "太慢了-加快时间");
			ModifyDelaytime(gDebitdetailWenv, -100);
ErrorLog(__FILE__, __LINE__, "TIME[%d]", gDebitdetailWenv->delaytime);
		}

		currentsamplenum = 0;
		currentsamplefast = 0;	
	}


	if (ret != 0)
		return ret;

	output=gumbo_parse(req->recvbody->base);	
	if(!output)
	{
		ErrorLog(__FILE__, __LINE__, "gumbo_parse failed");
		return SPIDER_INTERNAL_ERR;
	}

	memset(&user, 0x00, sizeof(user));
	ret = DebitDetail_GetUserInfo(output, &user);
	if (ret) {
		ErrorLog(__FILE__, __LINE__, "Parse_DetailHtml failed,loanid[%ld], ret[%d]",loanid, ret);
		goto E;
	}

	/* 打印信息 */
	PrintRenrendai_detail(&user, loanid);

E: 
	gumbo_destroy_output(&kGumboDefaultOptions,output);
	return ret;
}

/* 从MakeReq返回错误不会导致错误，只是表示没有任务可做 */
int DebitDetail_MakeReq(struct HttpReq **req)
{
	int ret = 0;
	char tempbuf[2048];
	char tempsessionid[100];
	long loanid = -1;

	do {
		/* 从前一个页面中获得sessionid */
		memset(tempsessionid, 0x00, sizeof(tempsessionid));
		/* 这里如果出错就直接返回，因为可能没有初始化sem或者已经被销毁sem */
		if (GetSessionId(tempsessionid))
			return -1;
		if (strlen(tempsessionid) == 0)
			return SPIDER_INVALID;

		/* 获得loanid */
		if (GetLoanId(&loanid) != 0) {
			return SPIDER_NOTFOUND_ERR;
		}

		*req = InitHttpReq();
		if (*req == NULL) {
			ErrorLog( __FILE__ , __LINE__ , "初始化httpreq失败");
			return SPIDER_MEM_ERR;
		}

		memset(tempbuf, 0x00, sizeof(tempbuf));
		sprintf(tempbuf, cookieDetail, tempsessionid);
		SetCookie(*req, tempbuf);
		//printf("detail cookie[%s]\n", tempbuf);

		memset(tempbuf, 0x00, sizeof(tempbuf));
		sprintf(tempbuf, urlDetail, loanid);
		//printf( "detail url[%s]\n", tempbuf);
		SetUrl(*req, tempbuf);

		struct DebitDetailInputStruct *input = (struct DebitDetailInputStruct*)(malloc(sizeof(struct DebitDetailInputStruct)));
		if (input == NULL) {
			ErrorLog( __FILE__ , __LINE__ , "获得列表详细信息初始化InputStruct失败");
			FreeHttpReq(*req);
			*req = NULL;
			ret = SPIDER_MEM_ERR;
			return ret;
		}
		memset(input, 0x00, sizeof(struct DebitDetailInputStruct));

		input->loanid = loanid;
		SetHttpReqInputData(*req, input, free);
		SetHeader(*req, headerDetail);

		char *x = (*req)->reqname;
		sprintf(x, "%ld", loanid);
		printf( "[make-detail][%ld]\n", loanid);
		return 0;
	}while(0);

	/* 没有页面了 */
	return SPIDER_NOTFOUND_ERR;
}

int DebitDetail_AfterParse(struct HttpReq* req)
{
	struct DebitDetailInputStruct *input = GetHttpReqInputData(req);

	if (req->result == 0 && req->rerrno == 0) {
		ErrorLog(__FILE__, __LINE__, "OK detail loanid[%ld]-result[%d]-rerrno[%d]", input->loanid, req->result, req->rerrno);
		gDebitdetailWenv->completetimes++;
		FreeHttpReq(req);
	}
	else {	
		const char *errmsg = GetStageErrorInfo(req);
		if (GetDetailErrorNo(req) == RSP_TOOFAST)
		{ 
			/* 如果太快引起的错误给他机会重新插入 */
			PushHttpReq(gDebitdetailWenv, req);
			ErrorLog(__FILE__, __LINE__, "TOOFAST detail loanid[%ld] push back", input->loanid);
			/* 这里不能释放内存 */
			//FreeHttpReq(req);
		}
		else {
			ErrorLog(__FILE__, __LINE__, "FAIL detail loanid[%ld]-result[%d]-rerrno[%d]", input->loanid, req->result, req->rerrno);
			gDebitdetailWenv->uncompletetimes++;
			FreeHttpReq(req);
		}
	}
	printf("[after-detail] loanid[%ld]-result[%d]-rerrno[%d]\n", input->loanid, req->result, req->rerrno);

	return 0;
}

int DebitDetail_FinishForWorker(struct WorkerEnv *wenv)
{
	free(gLoanids);
	/* TODO */
	//	while (pthread_mutex_destroy(&gLoanidarray_Lock) == EBUSY) {}

	return 0;
}

int DebitDetail_FinishForReq(struct HttpReq *req)
{
	struct DebitDetailInputStruct *input = NULL;

	if (req) {
		if (input) { 
			input = GetHttpReqInputData(req);
			ErrorLog( __FILE__ , __LINE__ , "提前退出导致req[%s]-loanid[%ld]未完成", req->reqname, input->loanid );
		}
	}

	FreeHttpReq(req);

	return 0;
}
